#include "FilterMaskFactory.h"
#include <exception>

FilterMask* FilterMaskFactory::GetUserDefinedFilterMask(void* filterParameter)
{
    if(filterParameter == NULL)
        throw new std::exception("FilterMaskFactory: Custom filter parameter = NULL");

    FilterMask* userDefinedFilter = reinterpret_cast<FilterMask*>(filterParameter);

    if(userDefinedFilter == NULL)
        throw new std::exception("FilterMaskFactory: Invalid user defined filter parameter = NULL");

    return userDefinedFilter;
}

FilterMask* FilterMaskFactory::GetFilterMask(FilterType type, void* filterParameter)
{
    switch(type)
    {
    case Filter_UserDefined:
        return GetUserDefinedFilterMask(filterParameter);
    case Filter_Weighted:
        return GetWeightedFilterMask(filterParameter);
    case Filter_Mean:
        return GetMeanFilterMask(filterParameter);
    case Filter_PointSharpening:
        return GetPointSharpeningFilterMask(filterParameter);
    case Filter_PointDetection:
        return GetPointDetectionFilterMask(filterParameter);
    case Filter_HorizontalLineSharpening:
        return GetHorizontalLineSharpeningFilterMask(filterParameter);
    case Filter_VerticalLineSharpening:
        return GetVerticalLineSharpeningFilterMask(filterParameter);
    case Filter_RightDiagonalLineSharpening:
        return GetRightDiagonalLineSharpeningFilterMask(filterParameter);
    case Filter_LeftDiagonalLineSharpening:
        return GetLeftDiagonalLineSharpeningFilterMask(filterParameter);
    case Filter_HorizontalLineDetection:
        return GetHorizontalLineDetectionFilterMask(filterParameter);
    case Filter_VerticalLineDetection:
        return GetVerticalLineDetectionFilterMask(filterParameter);
    case Filter_LeftDiagonalLineDetection:
        return GetLeftDiagonalLineDetectionFilterMask(filterParameter);
    case Filter_RightDiagonalLineDetection:
        return GetRightDiagonalLineDetectionFilterMaskFilterMask(filterParameter);
    }

    throw new std::exception("FilterType not supported");
}

FilterMask* FilterMaskFactory::GetWeightedFilterMask(void* filterParameter)
{
    static float weightFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {1.0 / 16.0 , 1.0 / 8.0 , 1.0 / 16.0,
     1.0 / 8.0  , 1.0 / 4.0 , 1.0 / 8.0,
     1.0 / 16.0 , 1.0 / 8.0 , 1.0 / 16.0};

    return FilterMask::From(weightFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize);
}

FilterMask* FilterMaskFactory::GetMeanFilterMask(void* filterParameter)
{
    if(filterParameter == NULL)
        throw new std::exception("FilterMaskFactory: Blur mean filter parameter = NULL");

    int maskSize = *(reinterpret_cast<int*>(filterParameter));
    FilterMask* meanFilterMask = new FilterMask(maskSize, maskSize);
    for(int y = 0; y < maskSize; y++)
    {
        for(int x = 0; x < maskSize; x++)
        {
            meanFilterMask->Mask[y][x] = 1.0 / (float)(maskSize * maskSize);
        }
    }

    return meanFilterMask;
}

FilterMask* FilterMaskFactory::GetPointSharpeningFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {-1.0 , -1.0 , -1.0,
    -1.0 , 9  , -1.0,
    -1.0  , -1.0 , -1.0};
    
    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_CutOff);
}


FilterMask* FilterMaskFactory::GetHorizontalLineSharpeningFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {0.0 , 1.0 , 0.0,
    0.0 , 1.0  , 0.0,
    0.0  , -1.0 , 0.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_CutOff);
}

FilterMask* FilterMaskFactory::GetVerticalLineSharpeningFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {0.0 , 0.0 , 0.0,
    1.0 , 1.0  , -1.0,
    0.0  , 0.0 , 0.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_CutOff);
}

FilterMask* FilterMaskFactory::GetLeftDiagonalLineSharpeningFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {0.0 , 0.0 , 1.0,
    0.0 , 1.0  , 0.0,
    -1.0  , 0.0 , 0.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_CutOff);
}

FilterMask* FilterMaskFactory::GetRightDiagonalLineSharpeningFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {1.0 , 0.0 , 0.0,
    0.0 , 1.0  , 0.0,
    0.0  , 0.0 , -1.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_CutOff);
}


FilterMask* FilterMaskFactory::GetPointDetectionFilterMask(void* filterParameter)
{
    static float edgeFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {-1.0 , -1.0 , -1.0,
    -1.0 , 8  , -1.0,
    -1.0  , -1.0 , -1.0};

    return FilterMask::From(edgeFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_Normalization);
}

FilterMask* FilterMaskFactory::GetHorizontalLineDetectionFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {1.0 , 2.0 , 1.0,
    0.0 , 0.0  , 0.0,
    -1.0  , -2.0 , -1.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_Normalization);
}

FilterMask* FilterMaskFactory::GetVerticalLineDetectionFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {1.0 , 0.0 , -1.0,
    2.0 , 0.0  , -2.0,
    1.0  , 0.0 , -1.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_Normalization);
}

FilterMask* FilterMaskFactory::GetRightDiagonalLineDetectionFilterMaskFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {2.0 , 1.0 , 0.0,
    1.0 , 0.0  , -1.0,
    0.0  , -1.0 , -2.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_Normalization);
}

FilterMask* FilterMaskFactory::GetLeftDiagonalLineDetectionFilterMask(void* filterParameter)
{
    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {0.0 , 1.0 , 2.0,
    -1.0 , 0.0  , 1.0,
    -2.0  , -1.0 , 0.0};

    return FilterMask::From(sharpenFilterMaskTemplate, PredefinedMaskSize, PredefinedMaskSize, PostProcessing_Normalization);
}

/*
FilterMask* FilterMaskFactory::GetVerticalLineSharpeningFilterMask(void* filterParameter)
{

    static float sharpenFilterMaskTemplate[PredefinedMaskSize][PredefinedMaskSize] =
    {0 , -1.0 , 0,
    0 , 1  , 0,
    0  , -1.0 , 0};

    FilterMask* sharpenFilterMask = new FilterMask(PredefinedMaskSize, PredefinedMaskSize, PostProcessing_CutOff);
    for(int y = 0; y < PredefinedMaskSize; y++)
    {
        for(int x = 0; x < PredefinedMaskSize; x++)
        {
            sharpenFilterMask->Mask[y][x] = sharpenFilterMaskTemplate[y][x];
        }
    }

    return sharpenFilterMask;
}*/